package com.amkai.aes.webservice.binary.objecthandler;

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Query;

import com.amkai.aes.aescommon.service.binary.job.inventory.DictionaryItemSearchJob;
import com.amkai.aes.aescommon.service.binary.job.inventory.DictionaryItemSearchParameters;
import com.amkai.aes.aescommon.service.binary.job.inventory.DictionaryItemSearchResult;
import com.amkai.aes.generatedbeans.dictionary.Item;
import com.amkai.aes.generatedbeans.organization.Department;
import com.amkai.aes.webservice.binary.JobObjectHandler;
import com.amkai.aes.webservice.binary.objecthandler.inventory.DictionaryQueryBuilder;
import com.amkai.common.extensions.hibernate.config.SiteManager;
import com.amkai.common.extensions.hibernate.config.manager.SessionManager;

public class DictionaryItemSearchHandler
		implements
		JobObjectHandler<DictionaryItemSearchJob, DictionaryItemSearchParameters, DictionaryItemSearchResult> {
	
	private static final Log log = LogFactory.getLog(DictionaryItemSearchHandler.class);

	

	@Override
	public DictionaryItemSearchResult process(DictionaryItemSearchJob job,
			DictionaryItemSearchParameters searchParams) throws Exception {

		long t1 = System.nanoTime();
		DictionaryItemSearchResult res = createResult(searchParams, job
				.getModuleDepartment());
		long t2 = System.nanoTime();
		
		log.debug(String.format("Item search elapsed %f seconds.",
				(t2 - t1) / 1000.0));
		return res;
	}

	private DictionaryItemSearchResult createResult(
			DictionaryItemSearchParameters searchParams,
			Department moduleDepartment) {
		DictionaryItemSearchResult result = new DictionaryItemSearchResult();
		DictionaryQueryBuilder queryBuilder = new DictionaryQueryBuilder(
				searchParams, moduleDepartment);
		SessionManager sm = null;
		try {
			sm = SiteManager.Start();
			sm.openSession();
			
			if (searchParams.getPageSize() > 0) {
				result.setRowCount(getResultCount(result, queryBuilder, sm));
			}
			
			result.setItems(getResultData(searchParams, moduleDepartment,
					queryBuilder, sm));
		} catch (Exception e) {
			log.error("", e);
		} finally {
			if (sm != null) {
				sm.closeSession();
			}
		}
		return result;
	}

	private Item[] getResultData(DictionaryItemSearchParameters searchParams,
			Department moduleDepartment, DictionaryQueryBuilder queryBuilder,
			SessionManager sm) {
		String dataQueryHQL = queryBuilder.getDataQuery();
		log.debug("Data query: " + dataQueryHQL);
		
		Query dataQuery = sm.execute(dataQueryHQL);
		setQueryParameters(queryBuilder, dataQuery);
		
		setupQueryPagination(searchParams, dataQuery);
		List<?> items = dataQuery.list();
		// KKORNEL: AES-4465
		//setTransientState(sm, moduleDepartment, items);
		return items.toArray(new Item[items.size()]);
	}

	private void setupQueryPagination(DictionaryItemSearchParameters searchParams,
			Query dataQuery) {
		if (searchParams.getPageSize() <= 0) return;
		
		dataQuery.setMaxResults(searchParams.getPageSize());
		if (searchParams.getPageNumber() > 0) {
			dataQuery.setFirstResult(searchParams.getPageSize()
					* searchParams.getPageNumber());
		} else {
			dataQuery.setFirstResult(0);
		}
	}

	private void setQueryParameters(DictionaryQueryBuilder queryBuilder,
			Query dataQuery) {
		for (int i=0; i<queryBuilder.getQueryParameterCount(); i++) {
			dataQuery.setParameter(i, queryBuilder.getQueryParameterAt(i));
		}
	}

	// KKORNEL: AES-11533 - Unused function
	/*private void setTransientState(SessionManager sm, Department moduleDepartment, List<Item> items) {
		try {
			// KKORNEL: AES-11533 - dm removed
			for (Item item : items) {
				// KKORNEL: AES-4465
				((Item)item).setTranzientActive(item.isActive());
			}
		} catch (Exception e) {
			log.debug("Error while setting active state: " + e.getMessage());
		}
	}*/

	private int getResultCount(DictionaryItemSearchResult result,
			DictionaryQueryBuilder queryBuilder, SessionManager sm) {

		String countQueryHQL = queryBuilder.getCountQuery();
		log.debug("Count query: " + countQueryHQL);
		
		Query countQuery = sm.execute(countQueryHQL);
		setQueryParameters(queryBuilder, countQuery);
		return ((Integer) countQuery.iterate().next())
				.intValue();
	}

}
